package com.detroitchowfree;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;

import com.detroitchowfree.Article;
import com.detroitchowfree.DetroitChowUtils;
import com.detroitchowfree.IArticleUpdateObserver;
import com.detroitchowfree.IStoreServiceObserver;
import com.detroitchowfree.StoreVO;
import com.detroitchowfree.LogUtil;
import com.detroitchowfree.TagCollection;
import com.detroitchowfree.tasks.FetchAllStoresTask;
import com.detroitchowfree.tasks.FetchArticlesTask;

import android.app.Application;
import android.content.Context;


public class StoreService extends Application implements IFetchStoresObserver, IFetchArticlesObserver{
	
//DatabaseAdapter dbAdapter;
	//private int storesInDB=0;
	private ArrayList<IStoreServiceObserver> storesObservers;
	private ArrayList<IArticleUpdateObserver> articleObservers;
	private ArrayList<Article> articles=null;
	private ArrayList<String> tags = new ArrayList<String>();
	public static final String ALL_TAG="ALL";
	
	private ArrayList<TagCollection> masterList=null;
	private ArrayList<StoreVO> allList=null;
	private ArrayList<StoreVO> mapList=null;
	private ArrayList<StoreVO> tagList=null;
	
	public static final String SELECTED_STORE_KEY="DetroitChowSetSelectedStore";
	public static final String SELECTED_STORE_NAME="DetroitChowSetSelectedStoreName";
	public static final String SELECTED_STORE_OVERRIDE="DetroitChowSetSelectedOverride";
	public static final String ACTIVITY_KEY="DetroitChowActivityKey";
	public static final String STREAM_VALUE="DetroitChowStreamValue";
	
	public static final String STORAGE_FILE="DetroitChowStorageFile";
	
	@Override
  public void onCreate() {
          //reinitialize variable
  }
	
	public void registerUpdateStoresObserver(IStoreServiceObserver o){
	  if(storesObservers == null)
	  	storesObservers = new ArrayList<IStoreServiceObserver>();
	  storesObservers.add(o);
  }
	
	public void unRegisterUpdateStoresObserver(IStoreServiceObserver o){
	  for (IStoreServiceObserver _o : storesObservers){
			if(_o == o){
				try{
					storesObservers.remove(o);
				}catch(Exception e){}
			}
		}
  }
	
	public void registerArticleUpdateObserver(IArticleUpdateObserver o){
		LogUtil.log("StoreService.registerArticleUpdateObserver", "registering Article Observer");
	  if(articleObservers == null)
	  	articleObservers = new ArrayList<IArticleUpdateObserver>();
	  articleObservers.add(o);
  }
	
	public void unRegisterArticleUpdateObserver(IArticleUpdateObserver o){
		for (IArticleUpdateObserver uo : articleObservers){
			if(uo == o){
				try{
					articleObservers.remove(o);
				}catch(Exception e){}
				
			}
		}
  }
	
	
	  
  public void notifyObserversStoreUpdate() {
    for (IStoreServiceObserver o: storesObservers) {
    	o.onStoreManagerUpdate();
    }
  }
  
  public void notifyObserversArticleUpdate(ArrayList<Article> result) {
  	LogUtil.log("StoreService.notifyObserversArticleUpdate", "articleObservers.size : " + articleObservers.size());
    for (IArticleUpdateObserver o: articleObservers) {
    	o.onArticleUpdate(result);
    }
  }
  
  public void initStores() {
    masterList = getMasterListFromFile();
    if(masterList == null || masterList.size() < 2){
      LogUtil.log("initStores", "init stores could not get stores");
      refreshStores();
    }else {
      LogUtil.log("initStores", "i believe master file was succesful");
      notifyObserversStoreUpdate();
    }
      
  }
  
  public void refreshStores() {
    fetchAllStores();
  }
  
  public void getArticles(int storeId){
  	LogUtil.log("StoreManager","getArticles storeId: " + storeId);
  	FetchArticlesTask fetchAllStoresTask = new FetchArticlesTask();
    fetchAllStoresTask.registerObserver(this);
    fetchAllStoresTask.execute(String.valueOf(storeId));
  }
  
  private void fetchAllStores() {
  	LogUtil.logTimer("StoreManager.fetchAllStores", Calendar.getInstance());
    FetchAllStoresTask fetchAllStoresTask = new FetchAllStoresTask();
    fetchAllStoresTask.registerObserver(this);
    fetchAllStoresTask.execute();
    
  }
  
  public void notifyFetchAllStoresComplete(ArrayList<TagCollection> result) {
    // TODO Auto-generated method stub
  	LogUtil.log("StoreService", "notifyFetchComplete");
  	masterList = result;
  	if(masterList == null)
  		LogUtil.log("notifyFetchAllStoresComplete", "masterList is null");
  	else
  		LogUtil.log("notifyFetchAllStoresComplete", "masterList is not null: " + masterList.size());
  	buildAllList();
  	buildMapList();
  	if(masterList != null)
  		serializeMasterList();
  	notifyObserversStoreUpdate(); 
  }
  
  

public ArrayList<StoreVO> getStoresList() {
  	if(allList == null || allList.size() == 0 )
  		buildAllList();
  	else
  		LogUtil.log("StoreService", "getStoresList allList is not null");
  	return allList;
  }
  
  private void buildAllList() {
  	allList = new ArrayList<StoreVO>();
		for(TagCollection tc : masterList) {
			if(tc.tag.equals(ALL_TAG)) {
				for(StoreVO svo : tc.stores) {
					if(svo.isListItem == 1) {
						allList.add(svo);
					}
				}
				Collections.sort(allList);
				break;
			}
		}
  }
  
  public ArrayList<StoreVO> getStoresList(String tag) {
  	tagList=new ArrayList<StoreVO>();
  	 for(TagCollection tc : masterList) {
 			if(tc.tag.equals(tag)) {
 				tagList.addAll(tc.stores);
 				Collections.sort(tagList);
 				break;
 			}
 		}
    return tagList;
  }
  
  public ArrayList<StoreVO> getStoresListForMap() {
  	if(mapList == null) {
  		buildMapList();
  	}
    return mapList;
  }
  
  private void buildMapList() {
  	
  	mapList = new ArrayList<StoreVO>();
		for(TagCollection tc : masterList) {
			if(tc.tag.equals(ALL_TAG)) {
				for(StoreVO svo : tc.stores) {
					if(svo.mapGroupId == svo.storeId)
						mapList.add(svo);
				}
				break;
			}
		}
  	
  }
  
  
  
  public ArrayList<String> getTags() {
  	/*
  	if(tags == null || tags.size() == 0 ){
  		tags = new ArrayList<String>();
  		for(TagCollection tc : masterList) {
  			if(!tc.tag.equals(ALL_TAG))
    		tags.add(tc.tag);
    	}
  		Collections.sort(tags);
  		tags.add(0, ALL_TAG);
  	}
  	*/
  	tags = new ArrayList<String>();
		for(TagCollection tc : masterList) {
			if(!tc.tag.equals(ALL_TAG))
  		tags.add(tc.tag);
  	}
		Collections.sort(tags);
		tags.add(0, ALL_TAG);
  	return tags;
  }
  
  
  public String getPhone(int id) {
  	for(StoreVO svo:allList){
  		if(id== svo.storeId)
  			return "tel:" + svo.phone;
  	}
  	return null;
  }
  
  public String getWeb(int id) {
  	for(StoreVO svo:allList){
  		if(svo.storeId == id)
  			return svo.website;
  	}
  	return null;
  }
  
  public StoreVO getStore(String s) {
  	for(StoreVO svo:allList){
  		if(s.toUpperCase().equals(svo.name.toUpperCase()))
  			return svo;
  	}
  	return null;
  }
  
  public StoreVO getStore(int id) {
  	for(StoreVO svo:allList){
  		if(id == svo.storeId)
  			return svo;
  	}
  	return null;
  }

	public void onFetchArticles(ArrayList<Article> result) {
	  // TODO Auto-generated method stub
	// TODO Auto-generated method stub
  	LogUtil.log("StoreService onFetchArticles","");
    if(result != null)
    	LogUtil.log("StoreService onFetchArticles","result was NOT null ");
    else
    	LogUtil.log("StoreService onFetchArticles","result was null: ");
    notifyObserversArticleUpdate(result); 
	  
  }
	
	public static String getMapAddressLine(StoreVO s) {
		if(s == null)
			return "";
		String result =null;
		if(s.address != null && s.city != null && s.state != null && s.zip != null)
			result=  s.address + "\n" + s.city + " " + s.state + " " + s.zip;
		else if(s.address != null && s.city != null && s.zip != null)
			result=  s.address + "\n" + s.city + " MI." + " " + s.zip;
		else if(s.address != null && s.city != null)
			result=  s.address + "\n" + s.city;
		else if(s.address != null)
			result=  s.address;
		
		result += "\n";
		if(s.phone != null)
			result += DetroitChowUtils.formattedPhoneNumber(s.phone) + "\n";
		
		if(s.website != null && s.website.length() > 0)
			result += s.website.replaceAll("^http://","") + "\n";
		
		return result;
	}

	public ArrayList<String> getAutoCompleteArray() {
		ArrayList<String> result = new ArrayList<String>();
		result.addAll(DetroitChowUtils.getAllStoreNames(allList));
	  result.addAll(DetroitChowUtils.getAllCities(allList));
	  result.addAll(tags);
	  java.util.Collections.sort(result);
	  return result;
  }

	public ArrayList<StoreVO> getSearch(String s) {
		ArrayList<StoreVO> result = new ArrayList<StoreVO>();
		ArrayList<StoreVO> storeResult =DetroitChowUtils.getSearchStoreNames(allList, s);
		if(storeResult != null)
			result.addAll(storeResult);
		
		ArrayList<StoreVO> cityResult = DetroitChowUtils.getSearchCities(result, allList, s);
		
		if(cityResult != null && cityResult.size() > 0 ) {
			
			if(result.size() ==0 )
				result.addAll(cityResult);
			else
				result = mergeStoreArrayList(result, cityResult);
		}
		
		ArrayList<StoreVO> tagResult = DetroitChowUtils.getSearchTags(result,allList, s);
		if(tagResult != null && tagResult.size() > 0 ) {
			if(result.size() == 0)
				result.addAll(tagResult);
			else
				result = mergeStoreArrayList(result, tagResult);
		}
		java.util.Collections.sort(result);
	  return result;
  }

	private ArrayList<StoreVO> mergeStoreArrayList(ArrayList<StoreVO> result,ArrayList<StoreVO> newArray) {
	  // TODO Auto-generated method stub
		if(result == null || result.size() == 0) 
			return newArray;
		
		if(newArray == null || newArray.size() == 0) 
			return result;
		
		boolean hasItem = false;
		for(StoreVO newItem : newArray) {
			hasItem = false;
			for(StoreVO target : result) {
				if(newItem.name.equals(target.name)) {
					hasItem= true;
					break;
				}
			}
			if(!hasItem)
				result.add(newItem);
		}
	  return result;
  }
	
	public boolean isStoresAlive() {
		if(masterList == null || allList == null)
			return false;
		return true;
	}
	
	private void serializeMasterList() {
    // TODO Auto-generated method stub
    try{
      FileOutputStream fos = openFileOutput(STORAGE_FILE, Context.MODE_PRIVATE);
      ObjectOutputStream oo=new ObjectOutputStream(fos);
      oo.writeObject(masterList); 
      //fos.write(masterList.getBytes());
      fos.close();
    }catch(Exception e){
      // Should handle this
      
    }
  }
	
	private ArrayList<TagCollection> getMasterListFromFile() {
	  ArrayList<TagCollection> result =null;
	  try{
	    FileInputStream fileIn = openFileInput(STORAGE_FILE);
	    ObjectInputStream in = new ObjectInputStream(fileIn);
	    result = (ArrayList<TagCollection>) in.readObject();
	    in.close();
	    fileIn.close();
	  }catch(Exception e){
	    LogUtil.log("getMasterListFromFile", "Exception in getMasterList");
	    e.printStackTrace();
	    LogUtil.log("getMasterListFromFile", e.getMessage());
	    return null;
	  }
	  
	  if(result == null)
	    LogUtil.log("getMasterListFromFile","result is null" );
	  else
	    LogUtil.log("getMasterListFromFile", "Size: " + result.size());
	  return result;
	}
	
}
